/*
 * Copyright 2010 Alexander Ulizko
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.ulizko.template.soy.utils;

import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.template.soy.SoyModule;

import javax.annotation.Nullable;
import java.util.List;

/**
 * Helper to instantiate Guice injector.
 * Whole code borrowed from {@link com.google.template.soy.MainClassUtils}
 */
public class MainUtils {

    /**
     * Private helper for createInjector().
     *
     * @param moduleName The name of the plugin module to instantiate.
     * @return A new instance of the specified plugin module.
     */
    private static Module instantiatePluginModule(String moduleName) {

        try {
            return (Module) Class.forName(moduleName).newInstance();

        } catch (ClassNotFoundException e) {
            throw new RuntimeException("Cannot find plugin module \"" + moduleName + "\".", e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Cannot access plugin module \"" + moduleName + "\".", e);
        } catch (InstantiationException e) {
            throw new RuntimeException("Cannot instantiate plugin module \"" + moduleName + "\".", e);
        }
    }

    /**
     * Creates a Guice injector that includes the SoyModule, a message plugin module, and maybe
     * additional plugin modules.
     *
     * @param msgPluginModuleName The full class name of the message plugin module. Required.
     * @param pluginModuleNames   Comma-delimited list of full class names of additional plugin modules
     *                            to include. Optional.
     * @return A Guice injector that includes the SoyModule, the given message plugin module, and the
     *         given additional plugin modules (if any).
     */
    public static Injector createInjector(
            String msgPluginModuleName, @Nullable String pluginModuleNames) {

        List<Module> guiceModules = Lists.newArrayListWithCapacity(2);

        guiceModules.add(new SoyModule());

        Preconditions.checkArgument(msgPluginModuleName != null && msgPluginModuleName.length() > 0);
        guiceModules.add(instantiatePluginModule(msgPluginModuleName));

        if (pluginModuleNames != null && pluginModuleNames.length() > 0) {
            for (String pluginModuleName : Splitter.on(',').split(pluginModuleNames)) {
                guiceModules.add(instantiatePluginModule(pluginModuleName));
            }
        }

        return Guice.createInjector(guiceModules);
    }
}
